﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Batch_Disc_Backup
{
    /// <summary>
    /// Shows a dialog of log information, so the user can look back at any failed processes,
    /// so then maybe try to manually copy those files again in windows explorer or something.
    /// </summary>
    public partial class FrmLog : Form
    {
        private List<DiscCopyInfo> infos = null;

        public FrmLog()
        {
            InitializeComponent();

            //Auto sets the column width to the longest subitem text
            colLogDetail.Width = -2;
            colLog.Width = -2;
        }

        private void FrmLog_Shown(object sender, EventArgs e)
        {
            UpdateCalendar();
            //Reset the time to now
            if (cboDate.Items.Count > 0)
                cboDate.SelectedIndex = cboDate.Items.Count - 1;
        }

        private void lvLogs_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateLogDetails();
        }

        private void cboDate_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateLogList();
        }

        /// <summary>
        /// Updates the date select combobox
        /// </summary>
        private void UpdateCalendar()
        {
            List<DateTime> dates = Log.GetLogDates();
            string selectedValue = ListItem.GetSelectedValue(cboDate);
            cboDate.Items.Clear();

            if (dates.Count == 0)
            {
                panDate.Visible = false;
                panContent.Visible = false;
                lblNoLogs.Text = string.Format("There are no logs");
                lblNoLogs.Visible = true;
                btnClearSelected.Enabled = false;
                btnClearAll.Enabled = false;
            }
            else
            {
                panDate.Visible = true;
                panContent.Visible = true;
                lblNoLogs.Visible = false;
                btnClearSelected.Enabled = true;
                btnClearAll.Enabled = true;

                foreach (DateTime date in dates)
                {
                    string val = date.ToString("yyyy-MM-dd");
                    cboDate.Items.Add(new ListItem(val));
                    if (selectedValue == val)
                        cboDate.SelectedIndex = cboDate.SelectedIndex = cboDate.Items.Count - 1;
                }
                if (cboDate.SelectedIndex == -1)
                    cboDate.SelectedIndex = cboDate.Items.Count - 1;
            }
        }

        /// <summary>
        /// Updates the log list on the left
        /// </summary>
        private void UpdateLogList()
        {
            string strSelectedDate = ListItem.GetSelectedValue(cboDate);
            if (strSelectedDate == null)
            {
                panContent.Visible = false;
                lblNoLogs.Visible = false;
                return;
            }
            panel1.Visible = true;
            DateTime selectedDate = DateTime.Parse(strSelectedDate);
            infos = Log.GetDiscCopyInfos(selectedDate);
            lvLogs.Items.Clear();
            if (infos.Count == 0)
            {
                panContent.Visible = false;
                lblNoLogs.Text = string.Format("There are no logs for {0}", selectedDate.ToString("yyyy/MM/dd"));
                lblNoLogs.Visible = true;
                return;
            }
            lblNoLogs.Visible = false;
            panContent.Visible = true;

            for (int i = 0; i < infos.Count; i++)
            {
                DiscCopyInfo info = infos[i];
                ListViewItem lvi = null;
                if (info.DateStarted == null)
                    lvi = new ListViewItem(info.VolumeLabel == null ? "..." : info.VolumeLabel); //I don't think that this can happen
                else
                    lvi = new ListViewItem(string.Format("{0}{1} - {2}", info.ExceptionCount > 0 ? "*":"",((DateTime)info.DateStarted).ToString("HH.mm.ss"), info.VolumeLabel));
                if (i == infos.Count - 1) lvi.Selected = true;
                lvLogs.Items.Add(lvi);
            }
        }


        /// <summary>
        /// Updates the log details on the right
        /// </summary>
        private void UpdateLogDetails()
        {
            //Set the background on the log item, as when the list is unfocused, the default blue bar disappears
            foreach (ListViewItem lvi in lvLogs.Items)
            {
                //lvi.Font = new Font(lvi.Font, lvi.Selected ? FontStyle.Bold : FontStyle.Regular);
                lvi.BackColor = lvi.Selected ? SystemColors.Highlight : lvLogs.BackColor;
                lvi.ForeColor = lvi.SubItems[0].Text.StartsWith("*") ? Color.Red : lvi.Selected ? SystemColors.HighlightText : SystemColors.ControlText;
            }

            if (lvLogs.SelectedIndices.Count == 0)
            {
                panDetails.Visible = false;
                return;
            }
            panDetails.Visible = true;
            DiscCopyInfo info = infos[lvLogs.SelectedIndices[0]];

            //List all the files that were are are to be copied
            lvLogDetails.Items.Clear();
            //Failed
            int failedCount = 0;
            foreach (FileToCopy fileToCopy in info.FilesToCopy)
            {
                if (fileToCopy.ExceptionMessage == null) continue;
                if (failedCount == 0)
                {
                    ListViewItem lviHeading = new ListViewItem("Failed:");
                    lviHeading.Font = new Font(lviHeading.Font, FontStyle.Bold);
                    lviHeading.ForeColor = Color.Red;
                    lviHeading.BackColor = SystemColors.ControlLight;
                    lvLogDetails.Items.Add(lviHeading);
                }
                ListViewItem lvi = new ListViewItem(fileToCopy.FormFile);
                lvi.ForeColor = Color.Red;
                failedCount++;
                lvLogDetails.Items.Add(lvi);
            }
            int uncopiedCount = 0;
            foreach (FileToCopy fileToCopy in info.FilesToCopy)
            {
                if (fileToCopy.CopyComplete) continue;
                if (uncopiedCount == 0)
                {
                    ListViewItem lviHeading = new ListViewItem("Uncopied:");
                    lviHeading.Font = new Font(lviHeading.Font, FontStyle.Bold);
                    lviHeading.BackColor = SystemColors.ControlLight;
                    lvLogDetails.Items.Add(lviHeading);
                }
                ListViewItem lvi = new ListViewItem(fileToCopy.FormFile);
                uncopiedCount++;
                lvLogDetails.Items.Add(lvi);
            }
            int successCount = 0;
            foreach (FileToCopy fileToCopy in info.FilesToCopy)
            {
                if (fileToCopy.ExceptionMessage != null || !fileToCopy.CopyComplete) continue;
                if (successCount == 0)
                {
                    ListViewItem lviHeading = new ListViewItem("Successful:");
                    lviHeading.Font = new Font(lviHeading.Font, FontStyle.Bold);
                    lviHeading.BackColor = SystemColors.ControlLight;
                    lviHeading.ForeColor = Color.Green;
                    lvLogDetails.Items.Add(lviHeading);
                }
                ListViewItem lvi = new ListViewItem(fileToCopy.FormFile);
                lvi.ForeColor = Color.Gray;
                successCount++;
                lvLogDetails.Items.Add(lvi);
            }

            //Setup the rest of the details
            lblFrom.Text = info.FromDir;
            lblTo.Text = info.ToDir;
            lblDateStarted.Text = info.DateStarted == null ? "--" : ((DateTime)info.DateStarted).ToString("yyyy/MM/dd HH.mm.ss");
            lblDateEnded.Text = info.DateEnded == null ? "--" : ((DateTime)info.DateEnded).ToString("yyyy/MM/dd HH.mm.ss");
            lblFileCount.Text = info.FileCount.ToString();
            lblSuccess.Text = successCount.ToString();
            if (successCount == info.FileCount)
            {
                lblSuccess.ForeColor = Color.LightGreen;
            }
            else
            {
                lblSuccess.ForeColor = SystemColors.ControlLight;
            }
            lblUncopied.Text = uncopiedCount.ToString() + (failedCount == 0 ? "" : " (" + failedCount + " failure" + (failedCount == 1 ? "" : "s") + ")");
            if (failedCount > 0)
            {
                lblUncopied.ForeColor = Color.Red;
                lblUncopied.Font = new Font(lblUncopied.Font, FontStyle.Bold);
            }
            else
            {
                lblUncopied.ForeColor = SystemColors.ControlLight;
                lblUncopied.Font = new Font(lblUncopied.Font, FontStyle.Regular);
            }
            lblDiscSize.Text = Quick.GetByteString(info.TotalFilesLength);
            lblAmountCopied.Text = Quick.GetByteString(info.TotalBytesCopied);

            //If the log is currently in progress, show the status of it
            if (true)
            {
                tblActive1.Visible = false;
                tblActive2.Visible = false;
            }
            else
            {
                //TODO If the DiscToCopy is found in one of the live DiscCopier proecsses,
                //grab that and show the current copy progress.
                //I probably won't end up doing this because it's too much effort and little
                //reason to do it.
                tblActive1.Visible = true;
                tblActive2.Visible = true;
            }
        }

        /// <summary>
        /// Right-Click lvLogs, Copy
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CopyListViewToClipboard(lvLogs);
        }

        /// <summary>
        /// Right click lvLogDetails, Copy
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void copyToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            CopyListViewToClipboard(lvLogDetails);
        }

        /// <summary>
        /// Copies the selected listviewitems to the clipboard
        /// </summary>
        /// <param name="lv"></param>
        private void CopyListViewToClipboard(ListView lv)
        {
            StringBuilder sb = new StringBuilder();
            foreach (ListViewItem lvi in lv.SelectedItems)
            {
                sb.AppendLine(lvi.SubItems[0].Text);
            }
            Clipboard.SetDataObject(sb.ToString(), true);
        }

        /// <summary>
        /// If right-click lvLogs and no items selected, don't show the context menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmLogs_Opening(object sender, CancelEventArgs e)
        {
            if (lvLogs.SelectedItems.Count == 0)
                e.Cancel = true;
        }

        /// <summary>
        /// If right-click lvLogDetails and no items selected, don't show the context menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmLogDetails_Opening(object sender, CancelEventArgs e)
        {
            if (lvLogDetails.SelectedItems.Count == 0)
                e.Cancel = true;
        }

        /// <summary>
        /// Opens the From directory in Windows Explorer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lblFrom_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            OpenDirectory(lblFrom);
        }

        /// <summary>
        /// Opens the To directory in Windows Explorer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lblTo_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            OpenDirectory(lblTo);
        }
        private void OpenDirectory(LinkLabel lbl)
        {
            if (Directory.Exists(lbl.Text))
                Process.Start(lbl.Text);
            else
                MessageBox.Show(this, "The directory no longer exists.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// Removes all the logs of the selected date
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearSelected_Click(object sender, EventArgs e)
        {
            string selectedDate = ListItem.GetSelectedValue(cboDate);
            if (selectedDate == null) return;

            if (MessageBox.Show(this, "All logs for " + selectedDate + " will be deleted.", "Confirm deletion", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.OK)
            {
                try
                {
                    Log.DeleteLogs(DateTime.Parse(selectedDate));
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                UpdateCalendar();
            }
        }

        /// <summary>
        /// Removes all of the logs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearAll_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(this, "All logs will be deleted.", "Confirm deletion", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.OK)
            {
                try
                {
                    Log.DeleteLogs();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                UpdateCalendar();
            }
        }

        /// <summary>
        /// Refreshes the displayed logs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            //TODO There should be an autorefresh, but it would be too much work for nothing because the code would need to be optimised
            UpdateCalendar();
        }

    }


}
